/*---------------------------------------------------------------------
 * File name: hal_timer.cpp
 *
 * Copyright (c) <2020-2022>, <ChenLong>
 *
 * All rights reserved.
 *
 * Author: ChenLong
 * Email: worldlong@foxmail.com
 *--------------------------------------------------------------------*/
#include "stm32g4xx.h"
#include "hal_system.h"
#include "hal_dma.h"
#if defined(USING_RT_THREAD)
#include "rtthread.h" 
#endif
/*
*/
const uint32_t dma_ch_table[16]={
  (uint32_t)DMA1_Channel1,(uint32_t)DMA1_Channel2,
  (uint32_t)DMA1_Channel3,(uint32_t)DMA1_Channel4,
  (uint32_t)DMA1_Channel5,(uint32_t)DMA1_Channel6,
  (uint32_t)DMA1_Channel7,(uint32_t)DMA1_Channel8,
  (uint32_t)DMA2_Channel1,(uint32_t)DMA2_Channel2,
  (uint32_t)DMA2_Channel3,(uint32_t)DMA2_Channel4,
  (uint32_t)DMA2_Channel5,(uint32_t)DMA2_Channel6,
  (uint32_t)DMA2_Channel7,(uint32_t)DMA2_Channel8 
};
const uint8_t dma_irqn_table[16]={
  DMA1_Channel1_IRQn, DMA1_Channel2_IRQn,
  DMA1_Channel3_IRQn, DMA1_Channel4_IRQn,
  DMA1_Channel5_IRQn, DMA1_Channel6_IRQn,
  DMA1_Channel7_IRQn, DMA1_Channel8_IRQn,
  DMA2_Channel1_IRQn, DMA2_Channel2_IRQn,
  DMA2_Channel3_IRQn, DMA2_Channel4_IRQn,
  DMA2_Channel5_IRQn, DMA2_Channel6_IRQn,
  DMA2_Channel7_IRQn, DMA2_Channel8_IRQn
};

static void (*dma_irq_hook[16])(void *param, uint32_t status) = {nullptr};
static void *dma_irq_hook_param[16]={nullptr};
/*
*/
void HAL_DMA::set_irq_hook(int index, void (*irq_hook)(void *param, uint32_t status), void *irq_hook_param)
{
  dma_irq_hook[index] = irq_hook;
  dma_irq_hook_param[index] = irq_hook_param;
}
/*
*/
uint32_t HAL_DMA::get_channel(int index)
{
  return dma_ch_table[index];
}
/*
*/
uint8_t HAL_DMA::get_irqn(int index)
{
  return dma_irqn_table[index];
}
/*
*/
int HAL_DMA::get_index(uint32_t dma_ch)
{
  if(dma_ch >= (uint32_t)DMA1_Channel1 && dma_ch <= (uint32_t)DMA1_Channel8) {
    return dma_ch - (uint32_t)DMA1_Channel1;
  } else if(dma_ch >= (uint32_t)DMA2_Channel1 && dma_ch <= (uint32_t)DMA2_Channel8) {
    return dma_ch - (uint32_t)DMA2_Channel1 + 8;
  } else {
    return -1;
  }
}
/*
*/
void HAL_DMA::enable(int index)
{
  ((DMA_Channel_TypeDef*)dma_ch_table[index])->CCR |= 0x01;
}
/*
*/
void HAL_DMA::disable(int index)
{
  ((DMA_Channel_TypeDef*)dma_ch_table[index])->CCR &= ~0x01;
}
/*****************************************************
 *                DMA
 ******************************************************/
#define DMA_CH_ST_POS(ch, val) (((uint32_t)val<<(ch-1)*4))
/*
*/
#ifdef __cplusplus
 extern "C" {
#endif
   
void DMA1_Channel1_IRQHandler()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  uint32_t status = DMA1->ISR & DMA_CH_ST_POS(1, 0x0F);
  if(status & DMA_CH_ST_POS(1, 0x02)) {
    if(dma_irq_hook[0] != nullptr) {
      dma_irq_hook[0](dma_irq_hook_param[0], status);
    }
  }
  //clear flag
  DMA1->IFCR |= DMA_CH_ST_POS(1, 0x0F);
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
/*
*/
void DMA1_Channel2_IRQHandler()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  uint32_t status = DMA1->ISR & DMA_CH_ST_POS(2, 0x0F);
  if(status & DMA_CH_ST_POS(2, 0x02)) {
    if(dma_irq_hook[1] != nullptr) {
      dma_irq_hook[1](dma_irq_hook_param[1], status);
    }
  }
  //clear flag
  DMA1->IFCR |= DMA_CH_ST_POS(2, 0x0F);
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
/*
*/
void DMA1_Channel3_IRQHandler()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  uint32_t status = DMA1->ISR & DMA_CH_ST_POS(3, 0x0F);
  if(status & DMA_CH_ST_POS(3, 0x02)) {
    if(dma_irq_hook[2] != nullptr) {
      dma_irq_hook[2](dma_irq_hook_param[2], status);
    }
  }
  //clear flag
  DMA1->IFCR |= DMA_CH_ST_POS(3, 0x0F);
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
/*
*/
void DMA1_Channel4_IRQHandler()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  uint32_t status = DMA1->ISR & DMA_CH_ST_POS(4, 0x0F);
  if(status & DMA_CH_ST_POS(4, 0x02)) {
    if(dma_irq_hook[3] != nullptr) {
      dma_irq_hook[3](dma_irq_hook_param[3], status);
    }
  }
  //clear flag
  DMA1->IFCR |= DMA_CH_ST_POS(4, 0x0F);
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
/*
*/
void DMA1_Channel5_IRQHandler()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  uint32_t status = DMA1->ISR & DMA_CH_ST_POS(5, 0x0F);
  if(status & DMA_CH_ST_POS(5, 0x02)) {
    if(dma_irq_hook[4] != nullptr) {
      dma_irq_hook[4](dma_irq_hook_param[4], status);
    }
  }
  //clear flag
  DMA1->IFCR |= DMA_CH_ST_POS(5, 0x0F);
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
/*
*/
void DMA1_Channel6_IRQHandler()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  uint32_t status = DMA1->ISR & DMA_CH_ST_POS(6, 0x0F);
  if(status & DMA_CH_ST_POS(6, 0x02)) {
    if(dma_irq_hook[5] != nullptr) {
      dma_irq_hook[5](dma_irq_hook_param[5], status);
    }
  }
  //clear flag
  DMA1->IFCR |= DMA_CH_ST_POS(6, 0x0F);
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
/*
*/
void DMA1_Channel7_IRQHandler()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  uint32_t status = DMA1->ISR & DMA_CH_ST_POS(7, 0x0F);
  if(status & DMA_CH_ST_POS(7, 0x02)) {
    if(dma_irq_hook[6] != nullptr) {
      dma_irq_hook[6](dma_irq_hook_param[6], status);
    }
  }
  //clear flag
  DMA1->IFCR |= DMA_CH_ST_POS(7, 0x0F);
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
/*
*/
void DMA1_Channel8_IRQHandler()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  uint32_t status = DMA1->ISR & DMA_CH_ST_POS(8, 0x0F);
  if(status & DMA_CH_ST_POS(8, 0x02)) {
    if(dma_irq_hook[7] != nullptr) {
      dma_irq_hook[7](dma_irq_hook_param[7], status);
    }
  }
  //clear flag
  DMA1->IFCR |= DMA_CH_ST_POS(8, 0x0F);
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}

/*
*/
void DMA2_Channel1_IRQHandler()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  uint32_t status = DMA2->ISR & DMA_CH_ST_POS(1, 0x0F);
  if(status & DMA_CH_ST_POS(1, 0x02)) {
    if(dma_irq_hook[0] != nullptr) {
      dma_irq_hook[0](dma_irq_hook_param[0], status);
    }
  }
  //clear flag
  DMA2->IFCR |= DMA_CH_ST_POS(1, 0x0F);
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
/*
*/
void DMA2_Channel2_IRQHandler()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  uint32_t status = DMA2->ISR & DMA_CH_ST_POS(2, 0x0F);
  if(status & DMA_CH_ST_POS(2, 0x02)) {
    if(dma_irq_hook[1] != nullptr) {
      dma_irq_hook[1](dma_irq_hook_param[1], status);
    }
  }
  //clear flag
  DMA2->IFCR |= DMA_CH_ST_POS(2, 0x0F);
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
/*
*/
void DMA2_Channel3_IRQHandler()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  uint32_t status = DMA2->ISR & DMA_CH_ST_POS(3, 0x0F);
  if(status & DMA_CH_ST_POS(3, 0x02)) {
    if(dma_irq_hook[2] != nullptr) {
      dma_irq_hook[2](dma_irq_hook_param[2], status);
    }
  }
  //clear flag
  DMA2->IFCR |= DMA_CH_ST_POS(3, 0x0F);
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
/*
*/
void DMA2_Channel4_IRQHandler()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  uint32_t status = DMA2->ISR & DMA_CH_ST_POS(4, 0x0F);
  if(status & DMA_CH_ST_POS(4, 0x02)) {
    if(dma_irq_hook[3] != nullptr) {
      dma_irq_hook[3](dma_irq_hook_param[3], status);
    }
  }
  //clear flag
  DMA2->IFCR |= DMA_CH_ST_POS(4, 0x0F);
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
/*
*/
void DMA2_Channel5_IRQHandler()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  uint32_t status = DMA2->ISR & DMA_CH_ST_POS(5, 0x0F);
  if(status & DMA_CH_ST_POS(5, 0x02)) {
    if(dma_irq_hook[4] != nullptr) {
      dma_irq_hook[4](dma_irq_hook_param[4], status);
    }
  }
  //clear flag
  DMA2->IFCR |= DMA_CH_ST_POS(5, 0x0F);
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
/*
*/
void DMA2_Channel6_IRQHandler()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  uint32_t status = DMA2->ISR & DMA_CH_ST_POS(6, 0x0F);
  if(status & DMA_CH_ST_POS(6, 0x02)) {
    if(dma_irq_hook[5] != nullptr) {
      dma_irq_hook[5](dma_irq_hook_param[5], status);
    }
  }
  //clear flag
  DMA2->IFCR |= DMA_CH_ST_POS(6, 0x0F);
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
/*
*/
void DMA2_Channel7_IRQHandler()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  uint32_t status = DMA2->ISR & DMA_CH_ST_POS(7, 0x0F);
  if(status & DMA_CH_ST_POS(7, 0x02)) {
    if(dma_irq_hook[6] != nullptr) {
      dma_irq_hook[6](dma_irq_hook_param[6], status);
    }
  }
  //clear flag
  DMA2->IFCR |= DMA_CH_ST_POS(7, 0x0F);
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}
/*
*/
void DMA2_Channel8_IRQHandler()
{
#if defined(USING_RT_THREAD)
  rt_interrupt_enter();
#endif
  uint32_t status = DMA2->ISR & DMA_CH_ST_POS(8, 0x0F);
  if(status & DMA_CH_ST_POS(8, 0x02)) {
    if(dma_irq_hook[7] != nullptr) {
      dma_irq_hook[7](dma_irq_hook_param[7], status);
    }
  }
  //clear flag
  DMA2->IFCR |= DMA_CH_ST_POS(8, 0x0F);
  
#if defined(USING_RT_THREAD)
  rt_interrupt_leave();
#endif
}


#ifdef __cplusplus
 }
#endif


